package com.eduagent.xwqeduagent.app.agent;

import com.eduagent.xwqeduagent.constant.FileConstant;
import com.eduagent.xwqeduagent.model.vo.WebScrapingResultVO;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Component
public class WebScrapingService {

    private static final int CONNECT_TIMEOUT = 10000; // 10秒连接超时
    private static final int READ_TIMEOUT = 15000; // 15秒读取超时
    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36";
    
    /**
     * 网页抓取
     * @param content 抓取内容(URL)
     * @param userId 用户ID
     * @param sessionId 会话ID
     * @return 网页抓取结果
     */
    public WebScrapingResultVO performWebScraping(String content, String userId, String sessionId) {
        log.info("开始网页抓取，URL：{}，用户ID：{}", content, userId);
        
        try {
            // 验证URL格式
            String url = normalizeUrl(content);
            if (!isValidUrl(url)) {
                return WebScrapingResultVO.builder()
                        .status("error")
                        .message("无效的URL格式：" + content)
                        .targetUrl(content)
                        .sessionId(sessionId)
                        .scrapeTime(new Date())
                        .build();
            }
            
            // 执行网页抓取
            Document doc = Jsoup.connect(url)
                    .userAgent(USER_AGENT)
                    .timeout(CONNECT_TIMEOUT)
                    .followRedirects(true)
                    .maxBodySize(5 * 1024 * 1024) // 限制5MB
                    .get();
            
            // 提取网页信息
            String title = extractTitle(doc);
            String textContent = extractTextContent(doc);
            List<String> links = extractLinks(doc, url);
            List<String> images = extractImages(doc, url);
            Map<String, String> metaInfo = extractMetaInfo(doc);
            
            // 保存抓取结果到文件
            String filePath = saveScrapingResult(url, title, textContent, links, images, metaInfo, sessionId);
            
            return WebScrapingResultVO.builder()
                    .status("success")
                    .message("网页抓取完成")
                    .targetUrl(url)
                    .title(title)
                    .textContent(textContent)
                    .links(links)
                    .images(images)
                    .filePath(filePath)
                    .sessionId(sessionId)
                    .scrapeTime(new Date())
                    .contentLength(textContent.length())
                    .build();
                    
        } catch (IOException e) {
            log.error("网页抓取IO异常：{}", e.getMessage());
            return WebScrapingResultVO.builder()
                    .status("error")
                    .message("网页抓取失败：" + getSimpleErrorMessage(e))
                    .targetUrl(content)
                    .sessionId(sessionId)
                    .scrapeTime(new Date())
                    .build();
        } catch (Exception e) {
            log.error("网页抓取失败", e);
            return WebScrapingResultVO.builder()
                    .status("error")
                    .message("网页抓取失败：" + e.getMessage())
                    .targetUrl(content)
                    .sessionId(sessionId)
                    .scrapeTime(new Date())
                    .build();
        }
    }
    
    /**
     * 规范化URL
     */
    private String normalizeUrl(String url) {
        if (cn.hutool.core.util.StrUtil.isBlank(url)) {
            return url;
        }
        
        url = url.trim();
        
        // 如果没有协议，默认添加http://
        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            url = "http://" + url;
        }
        
        return url;
    }
    
    /**
     * 验证URL是否有效
     */
    private boolean isValidUrl(String url) {
        try {
            new URL(url);
            return true;
        } catch (MalformedURLException e) {
            return false;
        }
    }
    
    /**
     * 提取网页标题
     */
    private String extractTitle(Document doc) {
        String title = doc.title();
        if (cn.hutool.core.util.StrUtil.isBlank(title)) {
            // 尝试从h1标签获取
            Element h1 = doc.selectFirst("h1");
            if (h1 != null) {
                title = h1.text();
            }
        }
        
        return cn.hutool.core.util.StrUtil.isBlank(title) ? "无标题" : title.trim();
    }
    
    /**
     * 提取网页文本内容
     */
    private String extractTextContent(Document doc) {
        // 移除script和style标签
        doc.select("script, style, nav, footer, aside, .advertisement, .ad").remove();
        
        // 优先提取main、article、content等主要内容区域
        Elements mainContent = doc.select("main, article, .content, .main-content, #content, #main");
        if (!mainContent.isEmpty()) {
            return cleanText(mainContent.text());
        }
        
        // 如果没有找到主要内容区域，提取body内容
        Element body = doc.body();
        if (body != null) {
            return cleanText(body.text());
        }
        
        return cleanText(doc.text());
    }
    
    /**
     * 清理文本内容
     */
    private String cleanText(String text) {
        if (cn.hutool.core.util.StrUtil.isBlank(text)) {
            return "";
        }
        
        // 替换多个空白字符为单个空格
        text = text.replaceAll("\\s+", " ");
        
        // 移除首尾空白
        text = text.trim();
        
        // 限制长度（避免内容过长）
        if (text.length() > 50000) {
            text = text.substring(0, 50000) + "...[内容过长，已截取]";
        }
        
        return text;
    }
    
    /**
     * 提取链接
     */
    private List<String> extractLinks(Document doc, String baseUrl) {
        Set<String> linkSet = new HashSet<>();
        Elements links = doc.select("a[href]");
        
        for (Element link : links) {
            String href = link.attr("href");
            if (cn.hutool.core.util.StrUtil.isNotBlank(href)) {
                String absoluteUrl = resolveAbsoluteUrl(href, baseUrl);
                if (absoluteUrl != null && isValidUrl(absoluteUrl)) {
                    linkSet.add(absoluteUrl);
                    if (linkSet.size() >= 50) { // 限制链接数量
                        break;
                    }
                }
            }
        }
        
        return new ArrayList<>(linkSet);
    }
    
    /**
     * 提取图片链接
     */
    private List<String> extractImages(Document doc, String baseUrl) {
        Set<String> imageSet = new HashSet<>();
        Elements images = doc.select("img[src]");
        
        for (Element img : images) {
            String src = img.attr("src");
            if (cn.hutool.core.util.StrUtil.isNotBlank(src)) {
                String absoluteUrl = resolveAbsoluteUrl(src, baseUrl);
                if (absoluteUrl != null && isImageUrl(absoluteUrl)) {
                    imageSet.add(absoluteUrl);
                    if (imageSet.size() >= 20) { // 限制图片数量
                        break;
                    }
                }
            }
        }
        
        return new ArrayList<>(imageSet);
    }
    
    /**
     * 提取元信息
     */
    private Map<String, String> extractMetaInfo(Document doc) {
        Map<String, String> metaInfo = new HashMap<>();
        
        // 提取meta标签信息
        Elements metaTags = doc.select("meta");
        for (Element meta : metaTags) {
            String name = meta.attr("name");
            String property = meta.attr("property");
            String content = meta.attr("content");
            
            if (cn.hutool.core.util.StrUtil.isNotBlank(content)) {
                if (cn.hutool.core.util.StrUtil.isNotBlank(name)) {
                    metaInfo.put(name, content);
                } else if (cn.hutool.core.util.StrUtil.isNotBlank(property)) {
                    metaInfo.put(property, content);
                }
            }
        }
        
        // 提取一些常用信息
        metaInfo.put("charset", doc.charset().name());
        
        return metaInfo;
    }
    
    /**
     * 解析绝对URL
     */
    private String resolveAbsoluteUrl(String url, String baseUrl) {
        try {
            if (url.startsWith("http://") || url.startsWith("https://")) {
                return url;
            }
            
            URL base = new URL(baseUrl);
            URL absolute = new URL(base, url);
            return absolute.toString();
        } catch (MalformedURLException e) {
            log.debug("无法解析URL：{}", url);
            return null;
        }
    }
    
    /**
     * 判断是否为图片URL
     */
    private boolean isImageUrl(String url) {
        if (cn.hutool.core.util.StrUtil.isBlank(url)) {
            return false;
        }
        
        String lowerUrl = url.toLowerCase();
        return lowerUrl.matches(".*\\.(jpg|jpeg|png|gif|bmp|webp|svg)(\\?.*)?$");
    }
    
    /**
     * 保存抓取结果到文件
     */
    private String saveScrapingResult(String url, String title, String textContent, 
                                    List<String> links, List<String> images, 
                                    Map<String, String> metaInfo, String sessionId) {
        try {
            String fileName = sessionId + "_scraping_result.json";
            String saveDir = FileConstant.FILE_SAVE_DIR + "/scraping/";
            
            // 确保目录存在
            cn.hutool.core.io.FileUtil.mkdir(saveDir);
            String filePath = saveDir + fileName;
            
            // 创建结构化的抓取结果数据
            cn.hutool.json.JSONObject scrapingData = new cn.hutool.json.JSONObject();
            scrapingData.put("target_url", url);
            scrapingData.put("title", title);
            scrapingData.put("text_content", textContent);
            scrapingData.put("links", links);
            scrapingData.put("images", images);
            scrapingData.put("meta_info", metaInfo);
            scrapingData.put("session_id", sessionId);
            scrapingData.put("scrape_time", new Date());
            scrapingData.put("content_length", textContent.length());
            scrapingData.put("links_count", links.size());
            scrapingData.put("images_count", images.size());
            
            // 保存文件
            cn.hutool.core.io.FileUtil.writeUtf8String(scrapingData.toString(), filePath);
            
            return filePath;
        } catch (Exception e) {
            log.error("保存抓取结果失败", e);
            return null;
        }
    }
    
    /**
     * 获取简化的错误信息
     */
    private String getSimpleErrorMessage(IOException e) {
        String message = e.getMessage();
        if (message == null) {
            return e.getClass().getSimpleName();
        }
        
        // 简化常见错误信息
        if (message.contains("timeout")) {
            return "连接超时";
        } else if (message.contains("Connection refused")) {
            return "连接被拒绝";
        } else if (message.contains("UnknownHostException")) {
            return "无法找到主机";
        } else if (message.contains("SSLException")) {
            return "SSL连接错误";
        } else {
            return message;
        }
    }
    
    /**
     * 网页抓取（返回JSON字符串）
     * @param content 抓取内容(URL)
     * @param userId 用户ID
     * @param sessionId 会话ID
     * @return JSON格式的抓取结果
     */
    public String scrapeWebPage(String content, String userId, String sessionId) {
        try {
            WebScrapingResultVO result = performWebScraping(content, userId, sessionId);
            return cn.hutool.json.JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            log.error("网页抓取转换JSON失败", e);
            
            WebScrapingResultVO errorResult = WebScrapingResultVO.builder()
                    .status("error")
                    .message("网页抓取失败：" + e.getMessage())
                    .targetUrl(content)
                    .sessionId(sessionId)
                    .scrapeTime(new Date())
                    .build();
            
            return cn.hutool.json.JSONUtil.toJsonStr(errorResult);
        }
    }
    
    /**
     * 批量网页抓取
     * @param urls URL列表
     * @param userId 用户ID
     * @param sessionId 会话ID
     * @return 批量抓取结果
     */
    public List<WebScrapingResultVO> performBatchWebScraping(List<String> urls, String userId, String sessionId) {
        List<WebScrapingResultVO> results = new ArrayList<>();
        
        for (String url : urls) {
            try {
                WebScrapingResultVO result = performWebScraping(url, userId, sessionId + "_" + results.size());
                results.add(result);
                
                // 添加延迟，避免过于频繁的请求
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                log.error("批量抓取URL失败：{}", url, e);
                results.add(WebScrapingResultVO.builder()
                        .status("error")
                        .message("抓取失败：" + e.getMessage())
                        .targetUrl(url)
                        .sessionId(sessionId)
                        .scrapeTime(new Date())
                        .build());
            }
        }
        
        return results;
    }
}